// File: jmcomic-core/src/main/java/dev/jukomu/common/postman/AbstractSessionPostman.java
package dev.jukomu.common.postman;

import dev.jukomu.common.util.json.JsonUtils;
import dev.jukomu.common.util.net.CommonResponse;
import dev.jukomu.common.util.net.IResponse;
import okhttp3.OkHttpClient;

import java.util.Map;
import java.util.stream.Collectors;

/**
 * 对应Python的AbstractSessionPostman，基于Session的Postman抽象实现。
 * 持有一个HTTP客户端Session（例如OkHttpClient实例）。
 */
public abstract class AbstractSessionPostman extends AbstractPostman {

    public static String POSTMAN_KEY = "abstract-session";

    protected OkHttpClient sessionClient; // 对应Python的session对象，这里假设是OkHttpClient

    /**
     * 构造函数。
     *
     * @param kwargs 初始化参数Map。
     */
    public AbstractSessionPostman(Map<String, Object> kwargs) {
        super(kwargs);
        // 在构造函数中创建SessionClient
        this.sessionClient = createSession(kwargs);
    }

    /**
     * 创建并配置HTTP Session Client（例如OkHttpClient）。
     *
     * @param kwargs 初始化参数Map
     * @return 配置好的OkHttpClient实例
     */
    protected abstract OkHttpClient createSession(Map<String, Object> kwargs);

    @Override
    protected Postman getRequestExecutor() {
        // 这里的SessionPostman自身就是执行器，因为它持有了sessionClient
        return new SessionClientExecutor(sessionClient);
    }

    @Override
    protected Postman postRequestExecutor() {
        return new SessionClientExecutor(sessionClient);
    }

    // 内部类，用于包装实际的OkHttpClient，使其符合Postman接口
    // 这样AbstractSessionPostman只需要关注Session的创建和管理，
    // 而不需要在自身直接实现get/post的OkHttp调用细节。
    protected static class SessionClientExecutor implements Postman {
        private final OkHttpClient client;

        public SessionClientExecutor(OkHttpClient client) {
            this.client = client;
        }

        // --- 以下是Postman接口方法的简化实现，仅用于内部调用 ---
        // 它们不会执行元数据合并、重试、代理链等复杂逻辑，
        // 那些逻辑由Postman代理链和AbstractPostman的beforeRequest处理。
        @Override
        public IResponse get(String url, Map<String, Object> kwargs) throws Exception {
            // 实现OkHttp的GET请求逻辑
            // kwargs需要被转换为OkHttp Request的参数
            okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder().url(url);

            // 处理headers
            Map<String, Object> headers = (Map<String, Object>) kwargs.get("headers");
            if (headers != null) {
                headers.forEach((k, v) -> requestBuilder.header(k, String.valueOf(v)));
            }

            // 处理params (query parameters)
            Map<String, Object> params = (Map<String, Object>) kwargs.get("params");
            if (params != null) {
                okhttp3.HttpUrl.Builder urlBuilder = okhttp3.HttpUrl.parse(url).newBuilder();
                params.forEach((k, v) -> urlBuilder.addQueryParameter(k, String.valueOf(v)));
                requestBuilder.url(urlBuilder.build());
            }

            // 处理timeout
            // OkHttp的timeout在OkHttpClient.Builder中设置，而不是Request.Builder
            // 这里假定sessionClient已配置好timeout，或在kwargs中处理并重新构建client（复杂）

            // 处理cookies (OkHttp通常通过CookieJar管理，或直接在header中设置)
            // Python的requests.Session的cookies是会话级的。
            // 这里的sessionClient如果通过CookieJar管理，则会自动处理。
            // 如果kwargs中显式传入cookies，可能需要手动添加到header。
            Map<String, Object> cookies = (Map<String, Object>) kwargs.get("cookies");
            if (cookies != null) {
                // Manually add cookies to header if not managed by CookieJar
                String cookieHeader = cookies.entrySet().stream()
                        .map(e -> e.getKey() + "=" + e.getValue())
                        .collect(Collectors.joining("; "));
                if (!cookieHeader.isEmpty()) {
                    requestBuilder.addHeader("Cookie", cookieHeader);
                }
            }

            okhttp3.Request request = requestBuilder.build();
            okhttp3.Response response = client.newCall(request).execute();
            return new CommonResponse(response);
        }

        @Override
        public IResponse post(String url, Map<String, Object> kwargs) throws Exception {
            // 实现OkHttp的POST请求逻辑
            okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder().url(url);

            // 处理headers
            Map<String, Object> headers = (Map<String, Object>) kwargs.get("headers");
            if (headers != null) {
                headers.forEach((k, v) -> requestBuilder.header(k, String.valueOf(v)));
            }

            // 处理params (query parameters), same as GET
            Map<String, Object> params = (Map<String, Object>) kwargs.get("params");
            if (params != null) {
                okhttp3.HttpUrl.Builder urlBuilder = okhttp3.HttpUrl.parse(url).newBuilder();
                params.forEach((k, v) -> urlBuilder.addQueryParameter(k, String.valueOf(v)));
                requestBuilder.url(urlBuilder.build());
            }

            // 处理data (form-encoded) 或 json (json body)
            okhttp3.RequestBody requestBody = null;
            Object data = kwargs.get("data");
            Object json = kwargs.get("json");

            if (json != null) {
                // Assume json is already a Map or simple POJO
                requestBody = okhttp3.RequestBody.create(JsonUtils.toJsonString(json), okhttp3.MediaType.parse("application/json; charset=utf-8"));
            } else if (data instanceof Map) {
                // Assume data is Map<String, String> for form-urlencoded
                okhttp3.FormBody.Builder formBuilder = new okhttp3.FormBody.Builder();
                ((Map<String, Object>) data).forEach((k, v) -> formBuilder.add(k, String.valueOf(v)));
                requestBody = formBuilder.build();
            } else if (data instanceof String) { // Raw string data
                requestBody = okhttp3.RequestBody.create((String) data, okhttp3.MediaType.parse("text/plain; charset=utf-8"));
            } else if (data instanceof byte[]) { // Raw byte data
                requestBody = okhttp3.RequestBody.create((byte[]) data, okhttp3.MediaType.parse("application/octet-stream"));
            }
            // Handling for files or MultipartEncoderMonitor will be in MultiPartPostman proxy

            requestBuilder.post(requestBody != null ? requestBody : okhttp3.RequestBody.create(new byte[0], null)); // Empty body if no data/json

            okhttp3.Request request = requestBuilder.build();
            okhttp3.Response response = client.newCall(request).execute();
            return new CommonResponse(response);
        }

        // --- 简化代理方法，不实现复杂逻辑 ---
        @Override
        public Postman copy() {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }

        @Override
        public <T> T getMetaData(String key, T defaultValue) {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }

        @Override
        public Map<String, Object> getMetaData() {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }

        @Override
        public Object getItem(String key) {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }

        @Override
        public void setItem(String key, Object value) {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }

        @Override
        public Postman getRootPostman() {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }

        @Override
        public Postman withFixUrl(String url) {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }

        @Override
        public Postman withRetry(int retryTimes, Class<? extends Postman> clazz) {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }

        @Override
        public Postman withMultiPart() {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }

        @Override
        public Postman withWrapResp(Class<? extends IResponse> clazz) {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }

        @Override
        public Postman withRedirectCatching(Class<? extends Postman> clazz) {
            throw new UnsupportedOperationException("Not supported in internal executor.");
        }
    }
}